import {defineStore} from "pinia";
import type {Book, Catalog} from "../types";
import {useApiBooks} from "../api/books.ts";
import { shareMemoryCache, type TableColumn} from "qyani-components";
import { computed, ref, watch } from "vue";
interface LRUTableColumn extends TableColumn{
    rank?:number
}
/**
 * 缓存: 缓存书籍信息
 */
const cache =  shareMemoryCache;
/**
 * 列定义
 */
export const columns = ref([
  {
    value:'id',
    label:'序号',
    order:true,
    rank:0
  },
  {
    value:'name',
    label:'书名',
    order:true,
    rank:0
  },
  {
    value:'cover',
    label:'封面'
  },
  {
    value:'author',
    label:'作者',
    order:true,
    rank:0
  },
  {
    value:'description',
    label:'简介',
  },
  {
    value:'words_cnt',
    label:'字数',
    order:true,
    rank:0
  },
  {
    value:'total_chapter',
    label:'章节数',
    width:'5rem',
    order:true,
    rank:0
  },
  {
    value:'tags',
    label:'标签'
  },
  {
    value:'operation',
    label:'操作'
  }
] as LRUTableColumn[]);
/**
 * 列定义拷贝,为了统计rank
 */
let columnCopy = ref(columns.value.map(item=>{
    /**
     * 解包
     */
    const obj = {...item}
    return obj;
}))


/**
 * @description 获取书籍排序条件 
 * - sort=field:1表示按照field升序排列
 * - sort=field-1表示按照field降序排列
 */
function getSelectConditions(){
    return columnCopy.value.filter(item=>'order' in item)
        .sort((a,b)=>b.rank! - a.rank!)
        .map(item=>`sort=${item.value}:${item.order?1:-1}`)
        .join('&')
}


/**
 * @description 获取一个空的书籍对象
 * @returns {Book} 空的书籍对象
 */
export function getEmptyBook():Book{
    return {
        id:0,
        name:'',
        author:'',
        cover:'',
        description:'',
        tags:'',
        total_chapter:0,
        words_cnt:0,
        category:'',
        created_at:''
    } satisfies Book
}
/**
 * @description 书籍Store,管理书籍获取等一系列状态,操作
 */
export const useBookStore = defineStore('book', {
    state: () => ({
        limit:10,
        loading:false,
        categories:[] as string[],
        currentCategory:'',
        categoriesCount:new Map<string,number>(),
        currentPage:1,
        books:[] as Book[],
    }),
    getters: {
        getCategoryBook:(state)=>{
            return state.books;
        },
        getCategoryCount:(state)=>{
           if(state.categoriesCount.has(state.currentCategory)){
             return Math.floor((state.categoriesCount.get(state.currentCategory)!+state.limit-1)/state.limit);
           }else{
            return 0;
           }
        },
    },
    actions: {
        setCurrentCategory(category:string){
            this.currentCategory = category;
            if(!this.categoriesCount.has(category)||!this.loading){
                this.loading = true;
                this.currentPage = 1;
                useApiBooks.getBookCategoryCount(category)
                .then(res=>{
                    if(res.success){
                        this.categoriesCount.set(category,res.data!.count);
                    }
                })
                .then(async ()=>{
                    const res = await useApiBooks.getBookBySelect(category,(this.currentPage-1)*this.limit,this.limit,getSelectConditions());
                    return res
                })
                .then(res=>{
                    if(res.success){
                        this.books = res.data!;
                        cache.set(`${category}_${this.currentPage}`,res.data!);
                    }
                })
                .finally(()=>{
                    this.loading = false;
                })
            }
        },
        setCurrentPage(page:number){
            this.currentPage=page;
            if(cache.has(`${this.currentCategory}_${page}`)){
                this.books = cache.get(`${this.currentCategory}_${page}`)!;
            }else if(!this.loading){
                this.loading=true;
                useApiBooks.getBookBySelect(this.currentCategory,(this.currentPage-1)*this.limit,this.limit,getSelectConditions())
                .then(res=>{
                    if(res.success){
                        this.books = res.data!;
                        cache.set(`${this.currentCategory}_${page}`,res.data!);
                    }
                })
                .finally(()=>{
                    this.loading = false;
                })
            }
        },
        async getBookById(id:number):Promise<Book>{
            const key = `book_${id}`;
            if (cache.has(key)){
                return cache.get(key)!
            }
            const {success,data} = await useApiBooks.getBookById(id);
            if(success){
                cache.set(key,data!);
                return data!;
            }
            return getEmptyBook();
        },
        async getCatalogById(id:number):Promise<Catalog[]>{
            const key = `catalog_${id}`;
            if (cache.has(key)){
                return cache.get(key)!
            }
            const {success,data} = await useApiBooks.getCatalogById(id);
            if(success){
                cache.set(key,data!);
                return data!;
            }
            return [];
        },
        async getBookChapterById(id:number){
            const {data} = await useApiBooks.getBookChapterById(id);
            return data||''
        },
        async getBookByList(book_ids:number[]){
            const booksFinded = [] as Book[];
            const booksNotFinded = [] as number[];
            for(const bookId of book_ids){
                if(cache.has(`book_${bookId}`)){
                    booksFinded.push(cache.get(`book_${bookId}`)!);
                }else{
                    booksNotFinded.push(bookId);
                }
            }
            if(booksNotFinded.length>0){
                const {success,data,message} = await useApiBooks.getBooksByList(booksNotFinded);
                if(success){
                    data!.forEach(book=>cache.set(`book_${book.id}`,book));
                    booksFinded.push(...data!);
                }else{
                    console.error(message);
                }
            }
            return booksFinded;
        },
        async getBookCategory(){ 
            const {success,data} = await useApiBooks.getBookCategory();
            if(success){
                this.categories = data!.sort((a,b)=>a.length-b.length);
            }
        },
    }
})

watch(
    ()=>columns.value,
    (newValue)=>{
        let temp = [...columnCopy.value].map(
            (item,index)=>{
                if('order' in item){
                    item.rank = 0;
                    if(item.order!==newValue[index]?.order){
                        item.rank = 1;
                        item.order = !item.order;
                    }
                }
                return item;
            }
        )
        columnCopy.value = temp;
        cache.clear();
        const store = useBookStore();
        store.setCurrentPage(1);
    }
)